import re
import html
from typing import Optional, List, Tuple
import logging

logger = logging.getLogger(__name__)


class TextHighlighter:
    """文本高亮处理类"""

    def __init__(self):
        self.highlight_start_tag = '<span class="highlight-match">'
        self.highlight_end_tag = '</span>'
        self.normal_start_tag = '<span class="highlight-normal">'
        self.normal_end_tag = '</span>'

    def escape_html(self, text: str) -> str:
        """转义HTML特殊字符"""
        return html.escape(text)

    def escape_regex(self, text: str) -> str:
        """转义正则表达式特殊字符"""
        return re.escape(text)

    def find_matches(self, original: str, search_text: str) -> List[Tuple[int, int, str]]:
        """
        在原文中查找匹配的文本位置
        返回: [(start_pos, end_pos, matched_text), ...]
        """
        matches = []

        if not original or not search_text:
            return matches

        # 1. 尝试精确匹配（区分大小写）
        search_pattern = re.escape(search_text)
        for match in re.finditer(search_pattern, original):
            matches.append((match.start(), match.end(), match.group()))

        # 2. 如果没有精确匹配，尝试不区分大小写
        if not matches:
            for match in re.finditer(search_pattern, original, re.IGNORECASE):
                matches.append((match.start(), match.end(), match.group()))

        # 3. 如果还没有匹配，尝试分词匹配
        if not matches:
            words = search_text.split()
            for word in words:
                if len(word) > 2:  # 只匹配长度大于2的单词
                    word_pattern = re.escape(word)
                    for match in re.finditer(word_pattern, original, re.IGNORECASE):
                        matches.append((match.start(), match.end(), match.group()))

        # 按位置排序，避免重叠
        matches.sort(key=lambda x: x[0])

        # 去除重叠的匹配
        filtered_matches = []
        last_end = -1
        for start, end, text in matches:
            if start >= last_end:
                filtered_matches.append((start, end, text))
                last_end = end

        logger.info(f"搜索文字: '{search_text}', 找到 {len(filtered_matches)} 个匹配")
        return filtered_matches

    def highlight_text(self, original: str, search_text: str) -> str:
        """
        高亮原文中的指定文字

        Args:
            original: 原文
            search_text: 要高亮的文字

        Returns:
            处理后的HTML字符串
        """
        if not original:
            return ""

        if not search_text or not search_text.strip():
            return f"{self.normal_start_tag}{self.escape_html(original).replace(chr(10), '<br>')}{self.normal_end_tag}"

        logger.info(f"开始处理高亮: 原文长度={len(original)}, 搜索文字='{search_text}'")

        # 查找所有匹配
        matches = self.find_matches(original, search_text.strip())

        if not matches:
            logger.info("没有找到匹配，返回全灰色文本")
            escaped_text = self.escape_html(original).replace('\n', '<br>')
            return f"{self.normal_start_tag}{escaped_text}{self.normal_end_tag}"

        # 构建结果字符串
        result_parts = []
        last_pos = 0

        for start, end, matched_text in matches:
            # 添加匹配前的普通文本
            if start > last_pos:
                before_text = original[last_pos:start]
                if before_text.strip():  # 只有非空文本才加灰色标签
                    escaped_before = self.escape_html(before_text)
                    result_parts.append(f"{self.normal_start_tag}{escaped_before}{self.normal_end_tag}")
                else:
                    result_parts.append(self.escape_html(before_text))

            # 添加高亮文本
            escaped_match = self.escape_html(matched_text)
            result_parts.append(f"{self.highlight_start_tag}{escaped_match}{self.highlight_end_tag}")

            last_pos = end

        # 添加最后剩余的普通文本
        if last_pos < len(original):
            remaining_text = original[last_pos:]
            if remaining_text.strip():
                escaped_remaining = self.escape_html(remaining_text)
                result_parts.append(f"{self.normal_start_tag}{escaped_remaining}{self.normal_end_tag}")
            else:
                result_parts.append(self.escape_html(remaining_text))

        # 合并结果并处理换行
        result = ''.join(result_parts)
        result = result.replace('\n', '<br>')

        logger.info(f"高亮处理完成，结果长度: {len(result)}")
        return result

    def highlight_multiple_terms(self, original: str, search_terms: List[str]) -> str:
        """
        高亮原文中的多个搜索词

        Args:
            original: 原文
            search_terms: 要高亮的文字列表

        Returns:
            处理后的HTML字符串
        """
        if not original or not search_terms:
            return self.highlight_text(original, "")

        # 合并所有搜索词的匹配结果
        all_matches = []
        for term in search_terms:
            matches = self.find_matches(original, term.strip())
            all_matches.extend(matches)

        # 按位置排序，去除重叠
        all_matches.sort(key=lambda x: x[0])
        filtered_matches = []
        last_end = -1

        for start, end, text in all_matches:
            if start >= last_end:
                filtered_matches.append((start, end, text))
                last_end = end

        if not filtered_matches:
            escaped_text = self.escape_html(original).replace('\n', '<br>')
            return f"{self.normal_start_tag}{escaped_text}{self.normal_end_tag}"

        # 构建结果（逻辑同单个搜索词）
        result_parts = []
        last_pos = 0

        for start, end, matched_text in filtered_matches:
            if start > last_pos:
                before_text = original[last_pos:start]
                if before_text.strip():
                    escaped_before = self.escape_html(before_text)
                    result_parts.append(f"{self.normal_start_tag}{escaped_before}{self.normal_end_tag}")
                else:
                    result_parts.append(self.escape_html(before_text))

            escaped_match = self.escape_html(matched_text)
            result_parts.append(f"{self.highlight_start_tag}{escaped_match}{self.highlight_end_tag}")
            last_pos = end

        if last_pos < len(original):
            remaining_text = original[last_pos:]
            if remaining_text.strip():
                escaped_remaining = self.escape_html(remaining_text)
                result_parts.append(f"{self.normal_start_tag}{escaped_remaining}{self.normal_end_tag}")
            else:
                result_parts.append(self.escape_html(remaining_text))

        result = ''.join(result_parts)
        result = result.replace('\n', '<br>')

        return result


# 创建全局实例
highlighter = TextHighlighter()


def highlight_text_in_content(original: str, search_text: str) -> str:
    """
    便捷函数：高亮文本中的指定内容

    Args:
        original: 原文
        search_text: 要高亮的文字

    Returns:
        处理后的HTML字符串
    """
    return highlighter.highlight_text(original, search_text)


def highlight_multiple_terms_in_content(original: str, search_terms: List[str]) -> str:
    """
    便捷函数：高亮文本中的多个搜索词

    Args:
        original: 原文
        search_terms: 要高亮的文字列表

    Returns:
        处理后的HTML字符串
    """
    return highlighter.highlight_multiple_terms(original, search_terms)


if __name__ == "__main__":
    # 测试代码
    test_original = """Unit1 Making Friends
Listen and tick.
Mike: Hello! I'm Mike Black.
Wu Binbin: Hi! My name is Wu Binbin.
Mike: Nice to meet you.
Wu Binbin: Nice to meet you too.
Listen and tick. 听录音选图。
Zip: Hello! My name is Zip. What's your name?
Dog: Hello! Zip! I am Jake!
Vocabulary:
friend /frend/ n. 朋友
hello /həˈləʊ/ int. 你好
name /neɪm/ n. 名字"""

    test_search = "friend"

    result = highlight_text_in_content(test_original, test_search)
    print("测试结果:")
    print(result)
